package org.springblade.task.job.base;

import com.google.common.collect.Lists;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.utils.DateUtils;
import org.springblade.task.base.entity.*;
import org.springblade.task.base.service.*;
import org.springblade.task.base.vo.BaseAudioChapterOrderVO;
import org.springblade.task.base.vo.BaseEbookOrderVO;
import org.springblade.task.base.vo.BaseNetChapterOrderVO;
import org.springblade.task.base.vo.BaseVirtualMoneyFlowLogVO;
import org.springblade.task.quartz.entity.QuartzTask;
import org.springblade.task.quartz.service.IQuartzTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @Title: 用户首次付费日期
 * @version V1.0
 */
@Component
public class BaseUserFirstPaymentDateJob {

	private static Logger logger = LoggerFactory.getLogger(BaseTaskInfoJob.class);

	@Autowired
	private IQuartzTaskService quartzTaskService;
	@Autowired
	private IBaseUserService baseUserService;
	@Autowired
	private IBaseVirtualMoneyFlowLogService baseVirtualMoneyFlowLogService;
	@Autowired
	private IBaseNetChapterOrderService BaseNetChapterOrderService;
	@Autowired
	private IBaseEbookOrderService BaseEbookOrderService;
	@Autowired
	private IBaseAudioChapterOrderService BaseAudioChapterOrderService;

	@Resource
	private ThreadPoolTaskExecutor threadPoolTaskExecutor;
	private static final int MAX_WAIT_TIME = 50; // future 超时时间50秒

	/**
	 * 1、简单任务示例（Bean模式）
	 */
	@XxlJob("baseUserFirstPaymentDateJob")
	public ReturnT<String> baseUserFirstPaymentDateJob(String param) throws Exception {
		System.out.println(DateUtils.currentDateTime() + " -- XXL-JOB, Hello World.");
		System.err.println("执行静态定时任务日期: " + BaseUserFirstPaymentDateJob.class.getSimpleName());
		QuartzTask quartzTask = quartzTaskService.queryByTaskName(BaseUserFirstPaymentDateJob.class.getSimpleName(), -7);
		// 今日
		String todayDate = DateUtils.crutDate();
		String taskDate = quartzTask.getTaskDate();
		while (taskDate.compareTo(todayDate) < 0) {
			// 当时间大于5点，跳出执行
//			if (DateUtils.getHour24() > 5) {
//				break;
//			}
			// 再加一个凌晨1点判断
			currMethod(taskDate);
			// 增加1天
			taskDate = DateUtils.dateAddDay(taskDate, 1);
		}
		quartzTask.setTaskDate(taskDate);
		quartzTaskService.saveQuartzTask(quartzTask);
		return ReturnT.SUCCESS;
	}

	/**
	 *
	 * @param taskDate
	 */
	public void currMethod(String taskDate) {

		// 查询首次付费用户
		List<String> pinList = baseUserService.queryFirstPaymentUserList("1870-01-01");
		if(!CollectionUtils.isEmpty(pinList)) {
			List<Future<List<String>>> futureResults = Lists.newArrayList();
			try {
				// 内存分页，每页取最大值
				int batchReadLimit = Math.max(999, 999);
				List<List<String>> resultPageParts = Lists.partition(pinList, batchReadLimit);
				CountDownLatch countDownLatch = new CountDownLatch(resultPageParts.size());

				for (List<String> userPinList : resultPageParts) {
					futureResults.add(threadPoolTaskExecutor.submit(new QueryThreadTask(countDownLatch, userPinList)));
				}
				countDownLatch.await(MAX_WAIT_TIME, TimeUnit.SECONDS);
			} catch (Exception e) {
				e.getMessage();
			}
		}
	}


	public void init() {
		logger.info("init");
	}

	public void destroy() {
		logger.info("destory");
	}


	// 内部类
	class QueryThreadTask implements Callable<List<String>> {

		private CountDownLatch countDownLatch;
		private List<String> pinList;

		public QueryThreadTask(CountDownLatch countDownLatch, List<String> pinList) {
			this.countDownLatch = countDownLatch;
			this.pinList = pinList;
		}

		@Override
		public List<String> call() throws Exception {
			List<String> listRpcResult = null;
			try {
				listRpcResult = query(pinList);
			} catch (Exception e) {
			} finally {
				countDownLatch.countDown();
			}
			return listRpcResult;
		}

		/**
		 * 数据查询
		 *
		 * @return
		 */
		private List<String> query(List<String> pinList) throws Exception{

			// 查询首次充值用户数据
			List<BaseVirtualMoneyFlowLogVO> firstRechargeUserList = baseVirtualMoneyFlowLogService.queryFirstRechargeUserList(pinList);
			Map<String, String> rechargeUserMap = new HashMap();
			for(BaseVirtualMoneyFlowLogVO entity: firstRechargeUserList) {
				rechargeUserMap.put(entity.getPin(), entity.getFirstPaymentDate());
			}
			// 查询网文电子书首次下单列表
			List<BaseNetChapterOrderVO> onlineFirstOrderList = BaseNetChapterOrderService.queryFirstOrderUserList(pinList);
			Map<String, String> onlineFirstOrderMap = new HashMap<>();
			for(BaseNetChapterOrderVO entity: onlineFirstOrderList) {
				onlineFirstOrderMap.put(entity.getPin(), entity.getFirstPaymentDate());
			}

			// 查询电子书首次下单列表
			List<BaseEbookOrderVO> ebookFirstOrderList = BaseEbookOrderService.queryFirstOrderUserList(pinList);
			Map<String, String>  ebookFirstOrderMap = new HashMap<>();
			for(BaseEbookOrderVO entity: ebookFirstOrderList) {
				ebookFirstOrderMap.put(entity.getPin(), entity.getFirstPaymentDate());
			}

			// 查询有声分章首次下单列表
			List<BaseAudioChapterOrderVO> audioFirstOrderList = BaseAudioChapterOrderService.queryFirstOrderUserList(pinList);
			Map<String, String> audioFirstOrderMap = new HashMap<>();
			for(BaseAudioChapterOrderVO entity: audioFirstOrderList) {
				audioFirstOrderMap.put(entity.getPin(), entity.getFirstPaymentDate());
			}

			List<BaseUser> userList = new ArrayList<>();
			BaseUser user = null;
			for(String pin: pinList) {
				user = new BaseUser();
				String firstPaymentDate = DateUtils.compare(DateUtils.compare(DateUtils.compare(onlineFirstOrderMap.get(pin), ebookFirstOrderMap.get(pin)),
				audioFirstOrderMap.get(pin)), rechargeUserMap.get(pin));
				user.setPin(pin);
				user.setFirstPaymentDate(firstPaymentDate);
				userList.add(user);
			}
			baseUserService.saveUpdateBatchFirstPaymentDate(userList);
			return null;
		}
	}
}
